package com.xxl.job.executor.utils;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;

public class RSAFactory {

    /**
     * 加密算法
     */
    private static final String ALGORITHM = "RSA";
    /**
     * 密钥长度
     */
    private static final int KEYSIZE = 1024;
    /**
     * 指定公钥存放文件
     */
    private static String PUBLIC_KEY_FILE = "PublicKey";
    /**
     * 指定私钥存放文件
     */
    private static String PRIVATE_KEY_FILE = "PrivateKey";

    /**
     * 生成密钥
     *
     * @throws Exception
     */
    public static void GenerateKey() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
        SecureRandom secureRandom = new SecureRandom();
        keyPairGenerator.initialize(KEYSIZE, secureRandom);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();
        ObjectOutputStream oos1 = null;
        ObjectOutputStream oos2 = null;
        try {
            String path = RSAUtil.class.getResource("./").getPath();
            oos1 = new ObjectOutputStream(new FileOutputStream(path + PUBLIC_KEY_FILE));
            oos2 = new ObjectOutputStream(new FileOutputStream(path + PRIVATE_KEY_FILE));
            oos1.writeObject(publicKey);
            oos2.writeObject(privateKey);
        } finally {
            if (oos1 != null) {
                oos1.close();
            }
            if (oos2 != null) {
                oos2.close();
            }
        }
    }

    public static PublicKey loadPublicKey() throws Exception {
        ObjectInputStream ois = null;
        PublicKey publicKey = null;
        try {
            ois = new ObjectInputStream(RSAUtil.class.getResourceAsStream(PUBLIC_KEY_FILE));
            publicKey = (PublicKey) ois.readObject();
        } finally {
            if (ois != null) {
                ois.close();
            }
        }
        return publicKey;
    }

    public static PrivateKey loadPrivateKey() throws Exception {
        ObjectInputStream ois = null;
        PrivateKey privateKey = null;
        try {
            ois = new ObjectInputStream(RSAUtil.class.getResourceAsStream(PRIVATE_KEY_FILE));
            privateKey = (PrivateKey) ois.readObject();
        } finally {
            if (ois != null) {
                ois.close();
            }
        }
        return privateKey;
    }

    public static PublicKey loadPublicKey(String publicKeyStr) throws Exception {
        byte[] bytes = new BASE64Decoder().decodeBuffer(publicKeyStr);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        return keyFactory.generatePublic(keySpec);
    }

    public static String publicKeyStr(PublicKey publicKey) {
        byte[] bytes = publicKey.getEncoded();
        return new BASE64Encoder().encode(bytes);
    }
}